<script setup lang="ts">
import { onMounted, ref } from 'vue'
import {
  RenderingEngine,
  Types,
  Enums,
  setVolumesForViewports,
  volumeLoader,
  utilities,
  geometryLoader,
  CONSTANTS
} from '@cornerstonejs/core'
import {
  initDemo,
  createImageIdsAndCacheMetaData,
  downloadSurfacesData

} from '@/helpers'
import { NSpin } from 'naive-ui'

import * as cornerstoneTools from '@cornerstonejs/tools'

const {
  SegmentationDisplayTool,
  ToolGroupManager,
  Enums: csToolsEnums,
  segmentation,
  ZoomTool,
  Types,
  TrackballRotateTool
} = cornerstoneTools
const { MouseBindings } = csToolsEnums
const { ViewportType, GeometryType } = Enums
const renderContainerRef = ref(null)
const idPrefix = 'surface-view'
const uuid = utilities.uuidv4()
const volumeId = `${idPrefix}-volumeId-${uuid}`

const toolGroupId3d = `${idPrefix}-toolGroupId-${uuid}`
const segmentationId = `${idPrefix}-segmentationId-${uuid}`
const viewportId2 = `${idPrefix}-viewportId2-${uuid}`

let renderingEngine

let surfaces

async function addSegmentationsToState() {
  // Download the surface data. Please note that this is a large file
  // and may take a while to download
  surfaces = await downloadSurfacesData()

  const geometriesInfo = surfaces.reduce(
    (acc: Map<number, string>, surface, index) => {
      const geometryId = surface.closedSurface.id
      geometryLoader.createAndCacheGeometry(geometryId, {
        type: GeometryType.SURFACE,
        geometryData: surface.closedSurface as Types.PublicSurfaceData
      })

      const segmentIndex = index + 1
      acc.set(segmentIndex, geometryId)

      return acc
    },
    new Map()
  )

  // Add the segmentations to state
  segmentation.addSegmentations([
    {
      segmentationId,
      representation: {
        // The type of segmentation
        type: csToolsEnums.SegmentationRepresentations.Surface,
        // The actual segmentation data, in the case of contour geometry
        // this is a reference to the geometry data
        data: {
          geometryIds: geometriesInfo
        }
      }
    }
  ])
}

async function run() {
  await initDemo()

  const toolGroup3d = ToolGroupManager.createToolGroup(toolGroupId3d)

  if (!toolGroup3d) {
    return
  }
  toolGroup3d.addTool(SegmentationDisplayTool.toolName)
  toolGroup3d.addTool(ZoomTool.toolName)
  toolGroup3d.addTool(TrackballRotateTool.toolName, {
    configuration: { volumeId }
  })

  toolGroup3d.setToolEnabled(SegmentationDisplayTool.toolName)


  toolGroup3d.setToolActive(TrackballRotateTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Primary
      }
    ]
  })

  toolGroup3d.setToolActive(ZoomTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Secondary // Right Click
      }
    ]
  })

  // Get Cornerstone imageIds for the source data and fetch metadata into RAM
  const imageIds = await createImageIdsAndCacheMetaData({
    StudyInstanceUID:
      '1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463',
    SeriesInstanceUID:
      '1.3.6.1.4.1.14519.5.2.1.7009.2403.226151125820845824875394858561',
    wadoRsRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb'
  })

  // Define a volume in memory
  const volume = await volumeLoader.createAndCacheVolume(volumeId, {
    imageIds
  })

  // Add some segmentations based on the source data volume

  await addSegmentationsToState()

  // Instantiate a rendering engine
  const renderingEngineId = 'myRenderingEngine'
  renderingEngine = new RenderingEngine(renderingEngineId)

  const viewportInputArray = [
    {
      viewportId: viewportId2,
      type: ViewportType.VOLUME_3D,
      element: renderContainerRef.value,
      defaultOptions: {
        background: <Types.Point3>[0.2, 0, 0.2]
      }
    }
  ]

  renderingEngine.setViewports(viewportInputArray)
  toolGroup3d.addViewport(viewportId2, renderingEngineId)

  volume.load()
  setVolumesForViewports(
    renderingEngine,
    [{ volumeId }],
    [viewportId2]
  ).then(() => {
    const viewport3d = renderingEngine.getViewport(viewportId2)
    const volumeActor = viewport3d.getDefaultActor().actor as Types.VolumeActor
    // 这里和体绘制采用的参数好像一样。
    utilities.applyPreset(
      volumeActor,
      CONSTANTS.VIEWPORT_PRESETS.find(
        (preset) => preset.name === 'CT-AAA'
      ) as any
    )

    const renderer = viewport3d.getRenderer()
    renderer.getActiveCamera().elevation(-70)
    viewport3d.setCamera({ parallelScale: 600 })

    viewport3d.render()
  })


  await segmentation.addSegmentationRepresentations(toolGroupId3d, [
    {
      segmentationId,
      type: csToolsEnums.SegmentationRepresentations.Surface
    }
  ])
  renderingEngine.render()
}

onMounted(async () => {
  await run()
  showLoadingRef.value = false
})

const showLoadingRef = ref(true)
</script>

<template>
  <div class="w-[600px] h-[500px]">
    <n-spin size="large" :show="showLoadingRef">
      <div class="w-[600px] h-[500px] bg-transparent  relative" ref="renderContainerRef">
      </div>
      <template #description>
        加载体数据中，大约需要1分钟
      </template>
    </n-spin>
  </div>
</template>

<style scoped>

</style>
